package tool.code.generater.sampler;


import tool.code.generater.DataType;
import tool.code.generater.config.JdbcConfig;
import tool.code.generater.struct.ColumnDef;
import tool.code.generater.struct.TableDef;
import tool.code.generater.util.CommonUtil;
import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.parser.SQLParserUtils;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.util.StringUtils;

import java.io.IOException;
import java.sql.JDBCType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DDLTableInfoSampler extends TableInfoSampler {
    public DDLTableInfoSampler(DbType dbType, String mappingConfigFile, JdbcConfig jdbcConfig) {
        super(dbType, mappingConfigFile, jdbcConfig);
    }

    @Override
    public List<TableDef> getColumns() {
        String script = jdbcConfig.getScript();
        if (StringUtils.isEmpty(script)) {
            return null;
        }
        if (script.startsWith("file://")) {
            String filename = script.replace("file://", "");
            try {
                String content = CommonUtil.ignoreLineAnnotation(filename);
                return getColumnsFromDDL(content);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return getColumnsFromDDL(script);
    }

    private List<TableDef> getColumnsFromDDL(String ddl) {
        String[] segments = ddl.split(";");
        List<TableDef> tableDefs = new ArrayList<>();
        for (String segment : segments) {

            TableDef tableDef = new TableDef();
            // 创建解析器配置
            SQLStatementParser statementParser = SQLParserUtils.createSQLStatementParser(ddl, dbType);
            SQLStatement sqlStatement = statementParser.parseStatement();
            if (sqlStatement instanceof SQLCreateTableStatement) {
                SQLCreateTableStatement statement = (SQLCreateTableStatement) sqlStatement;
                String tableName = statement.getTableName();
                List<ColumnDef> columnDefs = convertToColumnDefs(statement.getColumnDefinitions());
                tableDef.setName(tableName).setColumns(columnDefs).setComment(statement.getComment().toString());
            }
            tableDefs.add(tableDef);
        }
        return tableDefs;
    }

    protected DataType getFieldType(SQLDataType sqlDataType) {
        if (this.typeMapper == null) {
            return null;
        }
        int i = sqlDataType.jdbcType();
        JDBCType jdbcType = JDBCType.valueOf(i);
        return this.typeMapper.getJavaType(jdbcType.getName());
    }

    protected List<ColumnDef> convertToColumnDefs(List<SQLColumnDefinition> sqlColumnDefinitions) {
        List<ColumnDef> columnDefs = new ArrayList<>();
        for (SQLColumnDefinition sqlColumnDefinition : sqlColumnDefinitions) {
            ColumnDef columnDef = new ColumnDef();
            DataType fieldType = getFieldType(sqlColumnDefinition.getDataType());
            columnDef.setName(sqlColumnDefinition.getColumnName())
                    .setPrimaryKey(sqlColumnDefinition.getConstraints().stream().anyMatch(constraint -> Arrays.asList("PRIMARY KEY", "PRI").contains(constraint.toString())))
                    .setType(sqlColumnDefinition.getDataType().getName())
                    .setComment(sqlColumnDefinition.getComment().toString())
                    .setFieldType(fieldType.getJavaType())
                    .setJavaTypePackage(fieldType.getJavaTypePackage())
            ;
            columnDefs.add(columnDef);
        }
        return columnDefs;
    }


}
